home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / text / dtp / t1utils.lha / t1utils / unpost.c < prev   
C/C++ Source or Header  |  1993-06-17  |  7KB  |  320 lines

  1. /* unpost
  2. **
  3. ** This program converts Macintosh type-1 fonts stored in MacBinary (I or II)
  4. ** format or raw resource fork to PFA and PFB formats.
  5. **
  6. ** Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
  7. **
  8. ** Permission is hereby granted to use, modify, and distribute this program
  9. ** for any purpose provided this copyright notice and the one below remain
  10. ** intact. 
  11. **
  12. ** author: I. Lee Hetherington (ilh@lcs.mit.edu)
  13. */
  14.  
  15. /* Note: this is ANSI C. */
  16.  
  17. #ifndef lint
  18. static char sccsid[] =
  19.   "@(#) unpost.c 1.1 10:58:18 5/21/92";
  20. static char copyright[] =
  21.   "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
  22. #endif
  23.  
  24. #define BANNER "This is unpost 1.1.\n"
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28.  
  29. /* Some functions to read one, two, three, and four byte integers in 68000
  30.    byte order (most significant byte first). */
  31.  
  32. static int read_one(FILE *fi)
  33. {
  34.   return fgetc(fi);
  35. }
  36.  
  37. static int read_two(FILE *fi)
  38. {
  39.   int val;
  40.  
  41.   val = read_one(fi);
  42.   val = (val << 8) + read_one(fi);
  43.  
  44.   return val;
  45. }  
  46.  
  47. static long read_three(FILE *fi)
  48. {
  49.   long val;
  50.  
  51.   val = read_one(fi);
  52.   val = (val << 8) + read_one(fi);
  53.   val = (val << 8) + read_one(fi);
  54.  
  55.   return val;
  56. }  
  57.  
  58. static long read_four(FILE *fi)
  59. {
  60.   long val;
  61.  
  62.   val = read_one(fi);
  63.   val = (val << 8) + read_one(fi);
  64.   val = (val << 8) + read_one(fi);
  65.   val = (val << 8) + read_one(fi);
  66.  
  67.   return val;
  68. }
  69.  
  70. /* Function to write four byte length to PFB file: least significant byte
  71.    first. */
  72.  
  73. static void write_pfb_length(FILE *fo, long len)
  74. {
  75.   fputc(len & 0xff, fo);
  76.   len >>= 8;
  77.   fputc(len & 0xff, fo);
  78.   len >>= 8;
  79.   fputc(len & 0xff, fo);
  80.   len >>= 8;
  81.   fputc(len & 0xff, fo);
  82. }
  83.  
  84. static void reposition(FILE *fi, long absolute)
  85. {
  86.   if (fseek(fi, absolute, 0) == -1) {
  87.     fprintf(stderr, "error: fseek failed to position %d.\n", absolute);
  88.     fprintf(stderr, "       Is this file seekable?\n");
  89.     exit(1);
  90.   }
  91. }
  92.  
  93. static int hex_column = 0;              /* current column of hex */
  94.                           /* ASCII output */
  95.  
  96. static void output_hex_byte(FILE *fo, int b)
  97. {
  98.   static char *hex = "0123456789ABCDEF";
  99.  
  100.   if (hex_column > 62) {              /* 64 column output */
  101.     fputc('\n', fo);
  102.     hex_column = 0;
  103.   }
  104.   fputc(hex[b >> 4], fo);
  105.   fputc(hex[b & 0xf], fo);
  106.   hex_column += 2;
  107. }
  108.  
  109. /* Function to extract a particular POST resource.  Offset points to the four
  110.    byte length which is followed by the data.  The first byte of the POST data
  111.    specifies resource type: 1 for ASCII, 2 for binary, and 5 for end.  The
  112.    second byte is always zero. */
  113.  
  114. static void extract_data(FILE *fi, FILE *fo, long offset, int binary)
  115. {
  116.   enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 };
  117.   static enum PS_type last_type = PS_ascii;
  118.   long len, save_offset = ftell(fi);
  119.   int c;
  120.  
  121.   reposition(fi, offset);
  122.   len = read_four(fi) - 2;              /* subtract type field */
  123.   switch ((enum PS_type)read_one(fi)) {
  124.   case PS_ascii:
  125.     (void) read_one(fi);
  126.     if (binary) {
  127.       fputc(128, fo);
  128.       fputc(1, fo);
  129.       write_pfb_length(fo, len);
  130.       while (len--) {
  131.     if ((c = read_one(fi)) == '\r')          /* change \r to \n */
  132.       c = '\n';
  133.     fputc(c, fo);
  134.       }
  135.     } else {
  136.       if (last_type == PS_binary)
  137.     fputc('\n', fo);
  138.       while (len--) {
  139.     if ((c = read_one(fi)) == '\r')          /* change \r to \n */
  140.       c = '\n';
  141.     fputc(c, fo);
  142.       }
  143.     }
  144.     last_type = 1;
  145.     break;
  146.   case PS_binary:
  147.     (void) read_one(fi);
  148.     if (binary) {
  149.       fputc(128, fo);
  150.       fputc(2, fo);
  151.       write_pfb_length(fo, len);
  152.       while (len--)
  153.     fputc(read_one(fi), fo);
  154.     } else {
  155.       if (last_type != 2)
  156.     hex_column = 0;
  157.       while (len--)
  158.     output_hex_byte(fo, read_one(fi));
  159.       last_type = 2;
  160.     }
  161.     break;
  162.   case PS_end:
  163.     (void) read_one(fi);
  164.     if (binary) {
  165.       fputc(128, fo);
  166.       fputc(3, fo);
  167.     }
  168.     break;
  169.   }
  170.   reposition(fi, save_offset);
  171. }
  172.  
  173. static void usage(void)
  174. {
  175.   fprintf(stderr, "usage: unpost [-b] [-r] in-file [out-file]\n");
  176.   exit(1);
  177. }
  178.  
  179. int main(int argc, char **argv)
  180. {
  181.   FILE *fi, *fo;
  182.   long data_fork_size;
  183.   long res_offset, res_data_offset, res_map_offset, type_list_offset;
  184.   long post_type;
  185.   int num_types, num_of_type, num_extracted = 0, binary = 0, raw = 0;
  186.   int c;
  187.   extern int optind;
  188.   extern int getopt(int, char **, char*);
  189.  
  190.   fprintf(stderr, "%s", BANNER);
  191.  
  192.   /* parse command line */
  193.   while ((c = getopt(argc, argv, "br?")) != -1)
  194.     switch(c) {
  195.     case 'b':
  196.       ++binary;
  197.       break;
  198.     case 'r':
  199.       ++raw;
  200.       break;
  201.     default:
  202.       usage();
  203.     }
  204.  
  205.   /* open files */
  206.   if (argc - optind == 1) {
  207.     fi = fopen(argv[optind++], "r");
  208.     if (!fi) {
  209.       fprintf(stderr, "error: couldn't open `%s' for reading\n", 
  210.           argv[--optind]);
  211.       exit(1);
  212.     }
  213.     fo = stdout;
  214.   } else if (argc - optind == 2) {
  215.     fi = fopen(argv[optind++], "r");
  216.     if (!fi) {
  217.       fprintf(stderr, "error: couldn't open `%s' for reading\n", 
  218.           argv[--optind]);
  219.       exit(1);
  220.     }
  221.     fo = fopen(argv[optind++], "w");
  222.     if (!fo) {
  223.       fprintf(stderr, "error: couldn't open `%s' for writing\n", 
  224.           argv[--optind]);
  225.       exit(1);
  226.     }
  227.   } else {
  228.     usage();
  229.   }
  230.  
  231.   if (raw) {
  232.  
  233.     /* raw resource file */
  234.  
  235.     res_offset = 0;
  236.  
  237.   } else {
  238.  
  239.     /* MacBinary (I or II) file */
  240.  
  241.     /* SHOULD CHECK INTEGRITY OF MACBINARY HEADER HERE TO VERIFY THAT WE
  242.        REALLY HAVE A MACBINARY FILE.  MACBINARY-II-STANDARD.TXT DESCRIBES
  243.        AN APPROPRIATE VERIFICATION PROCEDURE. */
  244.  
  245.     /* read data and resource fork sizes in MacBinary header */
  246.     reposition(fi, 83);
  247.     data_fork_size = read_four(fi);
  248.     (void) read_four(fi);
  249.  
  250.     /* round data_fork_size up to multiple of 128 */
  251.     if (data_fork_size % 128)
  252.       data_fork_size += 128 - data_fork_size % 128;
  253.  
  254.     res_offset = 128 + data_fork_size;
  255.  
  256.   }    
  257.  
  258.   /* read offsets from resource fork header */
  259.   reposition(fi, res_offset);
  260.   res_data_offset = res_offset + read_four(fi);
  261.   res_map_offset = res_offset + read_four(fi);
  262.  
  263.   /* read type list offset from resource map header */
  264.   reposition(fi, res_map_offset + 24);
  265.   type_list_offset = res_map_offset + read_two(fi);
  266.  
  267.   /* read type list */
  268.   reposition(fi, type_list_offset);
  269.   num_types = read_two(fi) + 1;
  270.  
  271.   /* find POST type */
  272.   post_type = ('P' << 24) + ('O' << 16) + ('S' << 8) + 'T';
  273.  
  274.   while (num_types--) {
  275.     if (read_four(fi) == post_type) {
  276.       num_of_type = 1 + read_two(fi);
  277.       reposition(fi, type_list_offset + read_two(fi));
  278.       while (num_of_type--) {
  279.     (void) read_two(fi);              /* ID */
  280.     (void) read_two(fi);
  281.     (void) read_one(fi);
  282.     extract_data(fi, fo, res_data_offset + read_three(fi), binary);
  283.     ++num_extracted;
  284.     (void) read_four(fi);
  285.       }
  286.       break;
  287.     } else {
  288.       (void) read_two(fi);
  289.       (void) read_two(fi);
  290.     }
  291.   }
  292.  
  293.   fclose(fi);
  294.   if (fo != stdout) {
  295.     fclose(fo);
  296.     fprintf(stderr, "Extracted %d POST resource%s.\n", num_extracted,
  297.         (num_extracted == 1) ? "" : "s");
  298.   }
  299.  
  300.   return 0;
  301. }
  302.  
  303. /*
  304.  *  for Emacs...
  305.  *  Local Variables:
  306.  *  mode: C
  307.  *  comment-column: 50
  308.  *  fill-column: 79
  309.  *  c-indent-level: 2
  310.  *  c-continued-statement-offset: 2
  311.  *  c-brace-offset: -2
  312.  *  c-argdecl-indent: 2
  313.  *  c-label-offset: -2
  314.  *  End:
  315.  */
  316.  
  317.  
  318.  
  319.  
  320.